package com.uduemc.biso.node.module.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.uduemc.biso.node.core.entities.SPdtableTitle;
import com.uduemc.biso.node.core.entities.custom.pdtable.PdtableTitleFileConf;
import com.uduemc.biso.node.core.entities.custom.pdtable.PdtableTitleImageConf;
import com.uduemc.biso.node.module.mapper.SPdtableTitleMapper;
import com.uduemc.biso.node.module.service.SPdtableTitleService;

import cn.hutool.core.collection.CollUtil;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

@Service
public class SPdtableTitleServiceImpl implements SPdtableTitleService {

	public static final String ORDER_BY_ASC = "`s_pdtable_title`.`order_num` ASC, `s_pdtable_title`.`id` ASC";

	public static final String ORDER_BY_DESC = "`s_pdtable_title`.`order_num` DESC, `s_pdtable_title`.`id` DESC";

	@Autowired
	private SPdtableTitleMapper sPdtableTitleMapper;

	@Autowired
	private ObjectMapper objectMapper;

	@Override
	public SPdtableTitle insertAndUpdateCreateAt(SPdtableTitle sPdtableTitle) {
		sPdtableTitleMapper.insert(sPdtableTitle);
		SPdtableTitle findOne = findOne(sPdtableTitle.getId());
		Date createAt = sPdtableTitle.getCreateAt();
		if (createAt != null) {
			sPdtableTitleMapper.updateCreateAt(findOne.getId(), createAt, SPdtableTitle.class);
		}
		return findOne;
	}

	@Override
	public SPdtableTitle insert(SPdtableTitle sPdtableTitle) {
		sPdtableTitleMapper.insert(sPdtableTitle);
		return findOne(sPdtableTitle.getId());
	}

	@Override
	public SPdtableTitle insertSelective(SPdtableTitle sPdtableTitle) {
		sPdtableTitleMapper.insertSelective(sPdtableTitle);
		return findOne(sPdtableTitle.getId());
	}

	@Override
	public SPdtableTitle updateByPrimaryKey(SPdtableTitle sPdtableTitle) {
		sPdtableTitleMapper.updateByPrimaryKey(sPdtableTitle);
		return findOne(sPdtableTitle.getId());
	}

	@Override
	public SPdtableTitle updateByPrimaryKeySelective(SPdtableTitle sPdtableTitle) {
		sPdtableTitleMapper.updateByPrimaryKeySelective(sPdtableTitle);
		return findOne(sPdtableTitle.getId());
	}

	@Override
	public SPdtableTitle findOne(long id) {
		return sPdtableTitleMapper.selectByPrimaryKey(id);
	}

	@Override
	public SPdtableTitle findByHostSiteIdAndId(long id, long hostId, long siteId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("id", id);
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);

		return sPdtableTitleMapper.selectOneByExample(example);
	}

	@Override
	public SPdtableTitle findByHostSiteSystemIdAndId(long id, long hostId, long siteId, long systemId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("id", id);
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);
		criteria.andEqualTo("systemId", systemId);

		return sPdtableTitleMapper.selectOneByExample(example);
	}

	@Override
	public SPdtableTitle findMaxOrderNumInfoByHostSiteSystemId(long hostId, long siteId, long systemId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);
		criteria.andEqualTo("systemId", systemId);

		example.setOrderByClause(ORDER_BY_DESC);
		PageHelper.startPage(1, 1);

		return sPdtableTitleMapper.selectOneByExample(example);
	}

	@Override
	public List<SPdtableTitle> findInfosByHostSiteId(long hostId, long siteId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);

		example.setOrderByClause(ORDER_BY_ASC);

		return sPdtableTitleMapper.selectByExample(example);
	}

	@Override
	public List<SPdtableTitle> findInfosByHostSiteSystemId(long hostId, long siteId, long systemId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);
		criteria.andEqualTo("systemId", systemId);

		example.setOrderByClause(ORDER_BY_ASC);

		return sPdtableTitleMapper.selectByExample(example);
	}

	@Override
	public List<SPdtableTitle> findOkInfosByHostSiteSystemId(long hostId, long siteId, long systemId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);
		criteria.andEqualTo("systemId", systemId);
		criteria.andEqualTo("status", (short) 1);

		example.setOrderByClause(ORDER_BY_ASC);

		return sPdtableTitleMapper.selectByExample(example);
	}

	@Override
	public List<SPdtableTitle> findInfosByHostSiteIdAndIds(List<Long> ids, long hostId, long siteId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andIn("id", ids);
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);

		example.setOrderByClause(ORDER_BY_ASC);

		return sPdtableTitleMapper.selectByExample(example);
	}

	@Override
	public List<SPdtableTitle> findInfosByHostSiteSystemIdAndIds(List<Long> ids, long hostId, long siteId, long systemId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andIn("id", ids);
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);
		criteria.andEqualTo("systemId", systemId);

		example.setOrderByClause(ORDER_BY_ASC);

		return sPdtableTitleMapper.selectByExample(example);
	}

	@Override
	public int deleteByHostSiteId(long hostId, long siteId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);

		return sPdtableTitleMapper.deleteByExample(example);
	}

	@Override
	public int deleteByHostSiteSystemId(long hostId, long siteId, long systemId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);
		criteria.andEqualTo("systemId", systemId);

		return sPdtableTitleMapper.deleteByExample(example);
	}

	@Override
	public SPdtableTitle deleteByHostSiteIdAndId(long id, long hostId, long siteId) {
		SPdtableTitle sPdtableTitle = findByHostSiteIdAndId(id, hostId, siteId);
		if (sPdtableTitle == null) {
			return null;
		}
		sPdtableTitleMapper.deleteByPrimaryKey(id);
		return sPdtableTitle;
	}

	@Override
	public PageInfo<SPdtableTitle> findPageInfoAll(long hostId, long siteId, int pageNum, int pageSize) {
		Example example = new Example(SPdtableTitle.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);
		example.setOrderByClause(ORDER_BY_ASC);
		PageHelper.startPage(pageNum, pageSize);
		List<SPdtableTitle> list = sPdtableTitleMapper.selectByExample(example);
		PageInfo<SPdtableTitle> result = new PageInfo<>(list);
		return result;
	}

	@Override
	public PageInfo<SPdtableTitle> findPageInfoAll(long hostId, long siteId, long systemId, int pageNum, int pageSize) {
		Example example = new Example(SPdtableTitle.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);
		criteria.andEqualTo("systemId", systemId);
		example.setOrderByClause(ORDER_BY_ASC);
		PageHelper.startPage(pageNum, pageSize);
		List<SPdtableTitle> list = sPdtableTitleMapper.selectByExample(example);
		PageInfo<SPdtableTitle> result = new PageInfo<>(list);
		return result;
	}

	@Override
	@Transactional
	public boolean initSystemData(long hostId, long siteId, long systemId) {
		SPdtableTitle nameSPdtableTitle = new SPdtableTitle();
		SPdtableTitle imageSPdtableTitle = new SPdtableTitle();
		SPdtableTitle fileSPdtableTitle = new SPdtableTitle();
		SPdtableTitle categorySPdtableTitle = new SPdtableTitle();

		nameSPdtableTitle.setHostId(hostId).setSiteId(siteId).setSystemId(systemId);
		imageSPdtableTitle.setHostId(hostId).setSiteId(siteId).setSystemId(systemId);
		fileSPdtableTitle.setHostId(hostId).setSiteId(siteId).setSystemId(systemId);
		categorySPdtableTitle.setHostId(hostId).setSiteId(siteId).setSystemId(systemId);

		nameSPdtableTitle.setType((short) 5);
		imageSPdtableTitle.setType((short) 2);
		fileSPdtableTitle.setType((short) 3);
		categorySPdtableTitle.setType((short) 4);

		nameSPdtableTitle.setTitle("产品名称");
		imageSPdtableTitle.setTitle("图片");
		fileSPdtableTitle.setTitle("文件");
		categorySPdtableTitle.setTitle("分类");

		nameSPdtableTitle.setSiteSearch((short) 1).setStatus((short) 1).setProportion("-1").setOrderNum(1);
		categorySPdtableTitle.setSiteSearch((short) 0).setStatus((short) 1).setProportion("-1").setOrderNum(2);
		imageSPdtableTitle.setSiteSearch((short) 0).setStatus((short) 0).setProportion("-1").setOrderNum(3);
		fileSPdtableTitle.setSiteSearch((short) 0).setStatus((short) 0).setProportion("-1").setOrderNum(4);

		// 自定义的配置项
		nameSPdtableTitle.setConf("");
		// 分类
		categorySPdtableTitle.setConf("");
		// 图片、文件的默认配置项
		String imageConf = "";
		String fileConf = "";
		try {
			imageConf = objectMapper.writeValueAsString(new PdtableTitleImageConf());
			fileConf = objectMapper.writeValueAsString(new PdtableTitleFileConf());
		} catch (JsonProcessingException e) {
		}
		imageSPdtableTitle.setConf(imageConf);
		// 文件的默认配置项
		fileSPdtableTitle.setConf(fileConf);

		SPdtableTitle insert = insert(nameSPdtableTitle);
		if (insert == null) {
			throw new RuntimeException("写入 nameSPdtableTitle 失败！nameSPdtableTitle：" + nameSPdtableTitle);
		}
		insert = insert(categorySPdtableTitle);
		if (insert == null) {
			throw new RuntimeException("写入 categorySPdtableTitle 失败！categorySPdtableTitle：" + categorySPdtableTitle);
		}
		insert = insert(imageSPdtableTitle);
		if (insert == null) {
			throw new RuntimeException("写入 imageSPdtableTitle 失败！imageSPdtableTitle：" + imageSPdtableTitle);
		}
		insert = insert(fileSPdtableTitle);
		if (insert == null) {
			throw new RuntimeException("写入 fileSPdtableTitle 失败！fileSPdtableTitle：" + fileSPdtableTitle);
		}

		return true;
	}

	@Override
	@Transactional
	public boolean resetOrdernum(List<Long> ids, long hostId, long siteId, long systemId) {
		if (CollUtil.isEmpty(ids)) {
			return false;
		}
		List<SPdtableTitle> listSPdtableTitle = findInfosByHostSiteSystemIdAndIds(ids, hostId, siteId, systemId);
		if (CollUtil.isEmpty(listSPdtableTitle)) {
			return false;
		}
		if (CollUtil.size(listSPdtableTitle) != CollUtil.size(ids)) {
			return false;
		}
		for (int i = 1; i <= ids.size(); i++) {
			Long id = ids.get(i - 1);

			Optional<SPdtableTitle> findFirst = listSPdtableTitle.stream().filter(item -> {
				return item.getId().longValue() == id.longValue();
			}).findFirst();
			if (!findFirst.isPresent()) {
				throw new RuntimeException("未能找到 id：" + id + " 的数据，ids：" + ids + "，listSPdtableTitle：" + listSPdtableTitle);
			}
			SPdtableTitle sPdtableTitle = findFirst.get();
			sPdtableTitle.setOrderNum(i);
			updateByPrimaryKey(sPdtableTitle);
		}
		return true;
	}

	@Override
	public int totalByHostSiteId(long hostId, long siteId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);

		return sPdtableTitleMapper.selectCountByExample(example);
	}

	@Override
	public int totalByHostSiteSystemId(long hostId, long siteId, long systemId) {
		Example example = new Example(SPdtableTitle.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("siteId", siteId);
		criteria.andEqualTo("systemId", systemId);

		return sPdtableTitleMapper.selectCountByExample(example);
	}

	@Override
	public SPdtableTitle insertAfterById(SPdtableTitle sPdtableTitle, long afterId) {
		if (sPdtableTitle == null) {
			return null;
		}
		Long hostId = sPdtableTitle.getHostId();
		Long siteId = sPdtableTitle.getSiteId();
		Long systemId = sPdtableTitle.getSystemId();

		if (hostId == null || siteId == null || systemId == null) {
			return null;
		}

		if (afterId > 0) {
			if (findByHostSiteIdAndId(afterId, hostId, siteId) == null) {
				afterId = -1;
			}
		}

		if (afterId == 0) {
			afterId = -1;
		}

		if (afterId == -1L) {
			SPdtableTitle findMaxOrderNumSPdtableTitle = findMaxOrderNumInfoByHostSiteSystemId(hostId, siteId, systemId);
			if (findMaxOrderNumSPdtableTitle == null || findMaxOrderNumSPdtableTitle.getOrderNum() == null) {
				sPdtableTitle.setOrderNum(1);
			} else {
				// 获取到最大的 orderNum
				Integer orderNum = findMaxOrderNumSPdtableTitle.getOrderNum();
				sPdtableTitle.setOrderNum(++orderNum);
			}
			return insert(sPdtableTitle);
		} else if (afterId == -2L) {
			int orderNum = 1;
			sPdtableTitle.setOrderNum(orderNum++);
			SPdtableTitle insert = insert(sPdtableTitle);
			List<SPdtableTitle> listSPdtableTitle = findInfosByHostSiteId(hostId, siteId);
			if (CollUtil.isNotEmpty(listSPdtableTitle)) {
				for (SPdtableTitle item : listSPdtableTitle) {
					item.setOrderNum(orderNum++);
					updateByPrimaryKey(item);
				}
			}
			return insert;
		} else if (afterId > 0) {
			List<SPdtableTitle> listSPdtableTitle = findInfosByHostSiteId(hostId, siteId);
			SPdtableTitle insert = null;
			if (CollUtil.isNotEmpty(listSPdtableTitle)) {
				int orderNum = 1;
				for (SPdtableTitle item : listSPdtableTitle) {
					Integer on = item.getOrderNum();
					if (on == null || on.intValue() != orderNum) {
						item.setOrderNum(orderNum);
						updateByPrimaryKey(item);
					}

					if (item.getId().longValue() == afterId) {
						sPdtableTitle.setOrderNum(++orderNum);
						insert = insert(sPdtableTitle);
					}
					orderNum++;
				}
			}
			return insert;
		}
		return null;
	}

}
